package Code;

public class Matrix 
{
	double[][] matrix;
	
	/**********************************************
	 * Constructs a matrix object
	 * @param newMatrix the matrix being manipulated
	 **********************************************/
	public Matrix(double[][] newMatrix)
	{
		matrix = newMatrix;
	}
	
	/***********************************************
	 * Adds another matrix to this matrix
	 * @param other the other matrix
	 * @return the resulting matrix
	 * @throws Exception 
	 ***********************************************/
	public Matrix add(Matrix other) throws Exception
	{
		int rows = matrix.length;
		int cols = matrix[0].length;
		if (rows != other.matrix.length || cols != other.matrix[0].length)
			throw new Exception ("Invalid dimensions");
		double[][] tempMatrix = new double[rows][cols];
		
		for (int i = 0; i < rows; i++)
		{
			for (int j = 0; j < cols; j++)
			{
				tempMatrix[i][j] = matrix[i][j] + other.matrix[i][j];
			}
		}
		
		return new Matrix(tempMatrix);
	}
	
	/****************************************
	 * Transposes the current matrix
	 * @return the transposed matrix
	 */
	public Matrix transpose()
	{
		int row = matrix.length;
		int col = matrix[0].length;
		double[][] tempMatrix = new double[col][row];
		
		for (int i = 0; i < row; i++)
		{
			for (int j = 0; j < col; j++)
			{
				tempMatrix[j][i] = matrix[i][j];
			}
		}
		
		return new Matrix(tempMatrix);
	}
	
	/*************************************************
	 * Multiply the current matrix to another matrix
	 * @param other the matrix to multiply by
	 * 		this x other
	 * @return the product matrix
	 * @throws Exception 
	 */
	public Matrix multiply(Matrix other) throws Exception
	{
		int rowsThis = matrix.length;
		int colsThis = matrix[0].length;
		int rowsOther = other.matrix.length;
		int colsOther = other.matrix[0].length;
		if (colsThis != rowsOther)
			throw new Exception("Invalid dimensions");
		double[][] tempMatrix = new double[rowsThis][colsOther];
		
		for (int i = 0; i < rowsThis; i++)
		{
			for (int j = 0; j < colsOther; j++)
			{
				tempMatrix[i][j] = 0;
				for (int k = 0; k < colsThis; k++)
				{
					tempMatrix[i][j] += matrix[i][k] * other.matrix[k][j];
				}
			}
		}
		
		return new Matrix(tempMatrix);
	}
	
	@Override
	public boolean equals(Object obj)
	{
		Matrix o = (Matrix)obj;
		if (o.matrix.length != matrix.length)
			return false;
		if (o.matrix[0].length != matrix[0].length)
			return false;
		
		for (int row = 0; row < matrix.length; row++)
		{
			for (int col = 0; col < matrix[0].length; col++)
			{
				if (Double.compare(o.matrix[row][col], matrix[row][col]) != 0)
					return false;
			}
		}
		return true;
	}
	
	@Override
	public String toString()
	{
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < matrix.length; i++)
		{
			for (int j = 0; j < matrix[0].length; j++)
			{
				System.out.print(matrix[i][j] + "\t");
			}
			System.out.println();
		}
		
		return sb.toString();
	}
}
